﻿using System;
using System.Threading.Tasks;
using JetBrains.Annotations;

namespace K9Nano.Events
{
    /// <summary>
    /// Defines interface of the event bus.
    /// </summary>
    public interface IEventBus
    {
        #region Register

        void Register<TEventData, THandler>(string eventName)
            where TEventData : IEventData
            where THandler : IEventHandler<TEventData>
        {
            Register<THandler>(eventName);
        }

        void Register<TEventData, THandler>()
            where TEventData : IEventData
            where THandler : IEventHandler<TEventData>;

        void AsyncRegister<TEventData, THandler>([NotNull]string eventName)
            where TEventData : IEventData
            where THandler : IAsyncEventHandler<TEventData>
        {
            Register<THandler>(eventName);
        }

        void AsyncRegister<TEventData, THandler>()
            where TEventData : IEventData
            where THandler : IAsyncEventHandler<TEventData>;

        void Register<THandler>([NotNull]string eventName) where THandler : IEventHandler
        {
            Register(eventName, typeof(THandler));
        }

        /// <summary>
        /// 注册事件及其处理接口
        /// </summary>
        /// <param name="eventName">事件名称</param>
        /// <returns></returns>
        void Register([NotNull]string eventName, [NotNull]Type handler);

        #endregion

        #region Trigger

        void Trigger<TEventData>(TEventData eventData, bool internalOnly = false) where TEventData : IEventData;

        void Trigger(Type eventType, IEventData eventData, bool internalOnly = false);
       
        ValueTask TriggerAsync<TEventData>(TEventData eventData, bool internalOnly = false)
            where TEventData : IEventData;
   
        ValueTask TriggerAsync(Type eventType, IEventData eventData, bool internalOnly = false);

        /// <summary>
        /// 触发事件
        /// </summary>
        /// <param name="eventName">事件名称</param>
        /// <param name="eventData">事件数据</param>
        /// <param name="internalOnly">true表示仅在本地实例触发；否则在全平台触发</param>
        void Trigger([NotNull]string eventName, IEventData eventData, bool internalOnly = false);

        /// <summary>
        /// 触发事件
        /// </summary>
        /// <param name="eventName">事件名称</param>
        /// <param name="eventData">事件数据</param>
        /// <param name="internalOnly">true表示仅在本地实例触发；否则在全平台触发</param>
        ValueTask TriggerAsync([NotNull]string eventName, IEventData eventData, bool internalOnly = false);

        #endregion
    }
}